UFW
UFW (Uncomplicated Firewall) is a user-friendly firewall management tool for Linux, most commonly used on Ubuntu and Debian-based systems. It provides a simplified command-line interface for managing packet filtering rules that are ultimately enforced by the Linux kernel through Netfilter (via iptables, and on some systems nftables).
UFW became popular because it made host-based firewalling approachable for system administrators who did not want to manage complex iptables rule syntax directly. It has been included and supported as a standard firewall tool in Ubuntu for many years, is widely documented in the Ubuntu ecosystem, and is commonly used as a baseline security control for VPS and cloud servers.
UFW was introduced in the Ubuntu ecosystem as a simpler firewall interface compared to raw iptables. Over time it became the default “first firewall” choice for many Ubuntu server deployments because it balances simplicity with enough control for most host firewall needs.
When UFW Is a Good Fit
UFW is strongest when you need a reliable, maintainable host firewall policy with minimal complexity.
Common best-fit scenarios:
- VPS or cloud servers that need a baseline inbound policy (deny-by-default, allow only required services)
- Web servers (WordPress, OpenLiteSpeed, Nginx, Apache) that only require a small set of ports
- SSH hardening (custom ports, rate limiting, allow-listing trusted IPs)
- Simple outbound restrictions (blocking SMTP to prevent abuse, limiting egress to required services)
- Environments where operational simplicity and clarity are important (small teams, consistent automation)
Use UFW as your default host firewall on Ubuntu servers unless you have a clear requirement that demands a more advanced firewall framework.
When UFW Is Not Suitable
UFW is not designed to be a full network security platform. Avoid or reconsider UFW as the primary solution when you need:
- High-complexity firewalling with many dynamic rules or frequent rule changes at scale
- Advanced NAT/routing/firewall features that you want to manage entirely via higher-level policy frameworks
- Large enterprise environments that already standardize on a different firewall stack (direct
nftables,firewalld, vendor tooling, configuration management policies) - Deep Layer 7 filtering, WAF logic, bot management, or application-aware security (use a WAF, reverse proxy, or CDN security layer)
- Centralized fleet policy enforcement where a single source of truth must generate firewall policies across many host OS variants (often better served by orchestration + native firewall tooling)
UFW controls network access at the host firewall level (Layer 3/4). It does not replace a WAF, IDS/IPS, or application security controls.
Typical Alternatives
Choose based on environment and requirements:
| Tool / Approach | Best For |
|---|---|
ufw | Simple and reliable host firewall on Ubuntu/Debian; common VPS baseline |
nftables (direct) | Advanced/modern Linux firewall rules with full control and performance |
firewalld | Zone-based firewall management (common in RHEL/Fedora ecosystems) |
| Cloud security groups | First perimeter layer in cloud; should complement host firewall |
| CDN/WAF (Cloudflare, etc.) | Layer 7 protection, DDoS mitigation, bot filtering |
Prerequisites
- Ubuntu or Debian-based Linux server (VPS or bare metal)
sudoprivileges- Basic understanding of ports, IP addresses, TCP/UDP
Architecture Overview
UFW is a higher-level interface that converts human-readable rules into kernel firewall rules.
Core Syntax
ufw [global-options] <command> [parameters]
| Component | Meaning |
|---|---|
| - | -- |
global-options | Flags that affect command behavior (example: --force) |
command | Action or control command (example: allow, deny, status) |
parameters | Rule details (example: port, protocol, IP, interface) |
Global Options
| Option | Purpose |
|---|---|
| -- | |
--help | Show help and available commands |
--version | Show installed UFW version |
--force | Skip interactive confirmations (useful for automation) |
--verbose | More detailed output (commonly used with status) |
Command Groups
System Control
| Command | Purpose |
|---|---|
| -- | |
enable | Activate UFW and load rules |
disable | Deactivate UFW |
reload | Re-apply rules without disabling |
reset | Reset rules to defaults |
status | Show firewall status and rules |
Default Policy
Default policies apply when no rule matches.
sudo ufw default deny incoming
sudo ufw default allow outgoing
| Default Policy | Meaning |
|---|---|
| - | - |
deny incoming | Block inbound traffic unless explicitly allowed |
allow outgoing | Allow outbound traffic by default (common server baseline) |
Rule Evaluation Order
UFW evaluates rules in order. First match wins.
To inspect ordering:
sudo ufw status numbered
Rule Building Blocks
| Component | Meaning | Example |
|---|---|---|
| -- | -- | |
| Action | allow, deny, reject, limit | allow |
| Direction | in / out | allow in ... |
| Source | source IP/subnet | from 203.0.113.10 |
| Destination | destination IP | to any |
| Port | target port(s) | port 22 or 80,443 |
| Protocol | tcp/udp | proto tcp |
| Interface | restrict to NIC | on eth0 |
| Comment | documentation | comment "..." |
Examples:
sudo ufw allow 80/tcp comment "HTTP"
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp comment "SSH from office"
sudo ufw deny out 25/tcp comment "Block outbound SMTP"
Logging
Enable logging:
sudo ufw logging on
Set logging level:
sudo ufw logging low
sudo ufw logging medium
sudo ufw logging high
sudo ufw logging full
| Level | Typical Use |
|---|---|
| -- | |
low | Minimal logs (commonly blocked events) |
medium | Balanced auditing |
high / full | Debugging and deep analysis |
View logs:
sudo tail -f /var/log/ufw.log
Practical Use Cases
Safe Initialization (Avoid SSH Lockout)
sudo ufw allow 22/tcp comment "SSH"
sudo ufw allow 80,443/tcp comment "Web"
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw --force enable
sudo ufw status verbose
Limit SSH Brute Force Attempts
sudo ufw limit 22/tcp comment "Rate-limit SSH"
Restrict MySQL to Localhost Only
sudo ufw deny 3306/tcp comment "Block MySQL external"
sudo ufw allow from 127.0.0.1 to any port 3306 proto tcp comment "MySQL localhost"
Use Case: Change Default SSH Port
This example changes SSH from port 22 to 2222 and updates UFW rules safely.
Step 1: Allow the New SSH Port in UFW
sudo ufw allow 2222/tcp comment "SSH new port"
Verify rules:
sudo ufw status verbose
Step 2: Update SSH Daemon Configuration
Edit the SSH configuration file:
sudo nano /etc/ssh/sshd_config
Set the SSH port:
Port 2222
Restart SSH:
sudo systemctl restart ssh
Step 3: Test SSH Access on the New Port
From your local machine (open a new terminal session):
ssh -p 2222 username@your_server_ip
Step 4: Close Port 22 After Successful Test
sudo ufw delete allow 22/tcp
Verify final rules:
sudo ufw status numbered
Optional Hardening: Allow SSH Only From a Trusted IP
sudo ufw allow from 203.0.113.10 to any port 2222 proto tcp comment "SSH trusted IP"
sudo ufw deny 2222/tcp comment "SSH blocked except trusted IP"
OpenLiteSpeed and WordPress Baseline Template
Common ports:
| Port | Purpose |
|---|---|
| : | - |
| 80 | HTTP |
| 443 | HTTPS |
| 7080 | OpenLiteSpeed admin panel |
Template:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp comment "SSH"
sudo ufw limit 2222/tcp comment "Rate-limit SSH"
sudo ufw allow 80/tcp comment "HTTP"
sudo ufw allow 443/tcp comment "HTTPS"
sudo ufw allow from <your-ip> to any port 7080 proto tcp comment "OLS admin restricted"
sudo ufw --force enable
sudo ufw status verbose
Cloudflare-Only Access Pattern
Block direct access, then allow only Cloudflare IP ranges (example subset):
sudo ufw deny 80/tcp
sudo ufw deny 443/tcp
sudo ufw allow from 173.245.48.0/20 to any port 80,443 proto tcp comment "Cloudflare"
sudo ufw allow from 103.21.244.0/22 to any port 80,443 proto tcp comment "Cloudflare"
Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
| - | -- | -- |
| SSH fails after enabling UFW | SSH rule missing | Add ufw allow <ssh-port>/tcp then retry |
| Web not reachable | Ports not allowed | Allow 80/tcp and 443/tcp |
| Rules not taking effect | Reload needed | sudo ufw reload |
| Wrong rule precedence | Order mismatch | Use ufw status numbered + ufw insert |
Emergency Recovery
If you have console access (cloud provider console/serial), you can recover quickly:
sudo ufw disable
sudo ufw reset
sudo ufw allow 22/tcp comment "SSH recovery"
sudo ufw --force enable
Quick Command Reference
| Goal | Command |
|---|---|
| - | |
| Enable | sudo ufw enable |
| Disable | sudo ufw disable |
| Reload | sudo ufw reload |
| Reset | sudo ufw reset |
| Status | sudo ufw status verbose |
| Numbered rules | sudo ufw status numbered |
| Allow | sudo ufw allow 443/tcp |
| Deny | sudo ufw deny 3306/tcp |
| Limit | sudo ufw limit 2222/tcp |
| Delete by rule | sudo ufw delete allow 80/tcp |
| Delete by number | sudo ufw delete <num> |
Configuration Files
| Path | Purpose |
|---|---|
| -- | -- |
/etc/ufw/ufw.conf | UFW enablement at boot (ENABLED=yes/no) |
/etc/default/ufw | Defaults (including IPv6 setting) |
/etc/ufw/before.rules | Rules applied before user rules |
/etc/ufw/after.rules | Rules applied after user rules |
/etc/ufw/applications.d/ | Application profiles |
/var/log/ufw.log | UFW log output (if logging enabled) |